package com.userdemo.demo.config.intercepors;

import com.userdemo.demo.base.BaseService;
import com.userdemo.demo.common.sys.ServerResponse;
import com.userdemo.demo.constant.base.Const;
import com.userdemo.demo.entity.base.vo.BaseUserVO;
import com.userdemo.demo.enumeration.base.YesOrNoEnum;
import com.userdemo.demo.util.base.StringUtil;
import com.xiaoleilu.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * 　　* @description: 拦截器
 * 　　* @param ${tags}
 * 　　* @return ${return_type}
 * 　　* @throws
 * 　　* @author 陈宇
 * 　　* @date 2019-05-28
 *
 */

@Component
public class LoginInterceptor extends BaseService implements HandlerInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;



    //这个方法是在访问接口之前执行的，我们只需要在这里写验证登陆状态的业务逻辑，就可以在用户调用指定接口之前验证登陆状态了
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //每一个项目对于登陆的实现逻辑都有所区别，我这里使用最简单的Session提取User来验证登陆。
        //获取传入token名
        String loginToken = request.getParameter(Const.LOGINTOKEN);
        PrintWriter pw = response.getWriter();
        //重置response 不重置会报错
        response.reset();
        //设置编码格式
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        //这里的User是登陆时放入session的
        if(StringUtil.isEmpty(loginToken)){
            response.setHeader("Refresh","5; URL=login");
            pw.write(JSONUtil.toJsonPrettyStr(ServerResponse.createByErrorMessage("用户标识为空，请登录")));
            return false;
        }
        Object oUser =  redisTemplate.opsForValue().get(loginToken);
        if(null == oUser){
            response.setHeader("Refresh","5; URL=login");
            pw.write(JSONUtil.toJsonPrettyStr(ServerResponse.createByErrorMessage("用户标识已失效，请重新登录")));
            return false;
        }
        BaseUserVO user = (BaseUserVO) oUser;
        //如果session中没有user，表示没登陆
        if (user == null){
            //这个方法返回false表示忽略当前请求，如果一个用户调用了需要登陆才能使用的接口，如果他没有登陆这里会直接忽略掉
            //当然你可以利用response给用户返回一些提示信息，告诉他没登陆
            pw.write(JSONUtil.toJsonPrettyStr(ServerResponse.createByErrorMessage("用户标识已失效，请重新登录")));
            return false;
        }else {
            //此处可添加操作权限的控制，由于项目初期，所以先不做处理，后续有需求可以添加上，base_role_operation,base_operation表
            //续期redis
            redisTemplate.expire(loginToken,Const.CACHETIME,TimeUnit.HOURS);
            //更新用户为在线
            baseUserMapper.updateOnlineStatus(user.getUserName(),YesOrNoEnum.YES.getCode());
            return true;    //如果session里有user，表示该用户已经登陆，放行，用户即可继续调用自己需要的接口
        }
        //todo 判断用户操作权限
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }

}
